home *** CD-ROM | disk | FTP | other *** search
/ APDL Other Worlds / APDL Other Worlds Collection.iso / SF3000 / Extras / !SFtoSpr / c / Utils < prev   
Encoding:
Text File  |  2003-11-06  |  14.4 KB  |  485 lines

  1. /*
  2.  *  SFtoSpr - Star Fighter 3000 graphics converter
  3.  *  Utility functions
  4.  *  Copyright (C) 2000  Chris Bazley
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public Licence as published by
  8.  *  the Free Software Foundation; either version 2 of the Licence, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public Licence for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public Licence
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. /* ANSI library files */
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <stdbool.h>
  26.  
  27. /* RISC OS library files */
  28. #include "kernel.h"
  29. #include "toolbox.h"
  30. #include "event.h"
  31. #include "window.h"
  32. #include "wimplib.h"
  33. #include "gadgets.h"
  34. #include "swis.h"
  35. #include "saveas.h"
  36. #include "flex.h"
  37.  
  38. /* My library files */
  39. #include "err.h"
  40. #include "msgtrans.h"
  41. #include "hourglass.h"
  42. #include "Macros.h"
  43. #include "Loader.h"
  44. #include "SFformats.h"
  45. #include "SprFormats.h"
  46. #include "NoBudge.h"
  47. #include "FilePerc.h"
  48.  
  49. /* Local headers */
  50. #include "SFgfxconv.h"
  51. #include "Main.h"
  52. #include "Utils.h"
  53.  
  54. /* ----------------------------------------------------------------------- */
  55. /*                       Function prototypes                               */
  56.  
  57. static bool _check_anims_limits(char *anims_array, int last_tilenum);
  58.  
  59. /* ----------------------------------------------------------------------- */
  60. /*                         Public functions                                */
  61.  
  62. _kernel_oserror *open_above_iconbar(unsigned int flags, ObjectId id, ObjectId parent, ComponentId parent_component)
  63. {
  64.   /* Open window horizontally centred on pointer, above iconbar */
  65.   WimpGetPointerInfoBlock pointerinfo;
  66.   WindowShowObjectBlock showblock;
  67.   WimpGetWindowStateBlock winstate;
  68.   ObjectId win_id;
  69.  
  70.   THROW(wimp_get_pointer_info(&pointerinfo))
  71.   THROW(saveas_get_window_id(0, id, &win_id))
  72.   THROW(window_get_wimp_handle(0, win_id, &(winstate.window_handle)))
  73.   THROW(wimp_get_window_state(&winstate))
  74.  
  75.   showblock.visible_area.xmin = pointerinfo.x - (winstate.visible_area.xmax - winstate.visible_area.xmin)/2;
  76.   showblock.visible_area.ymin = 96 + (winstate.visible_area.ymax - winstate.visible_area.ymin);
  77.   return toolbox_show_object(flags, id, Toolbox_ShowObject_TopLeft, &showblock, parent, parent_component);
  78. }
  79.  
  80. /*
  81.  * File loading routines
  82.  */
  83.  
  84. _kernel_oserror *load_compressed(char *filepath, flex_ptr buffer_anchor)
  85. {
  86.   return perc_operation(FILEPERC_OP_DECOMP, filepath, 0, buffer_anchor);
  87. }
  88.  
  89. /* ----------------------------------------------------------------------- */
  90.  
  91. _kernel_oserror *load_sprites(char *filepath, flex_ptr buffer_anchor)
  92. {
  93.   return perc_operation(FILEPERC_OP_LOAD, filepath, 1u<<31, buffer_anchor);
  94. }
  95.  
  96. /* ----------------------------------------------------------------------- */
  97.  
  98. _kernel_oserror *load_animations(char *file_path, flex_ptr buffer)
  99. {
  100.   /* A LoaderFileHandler for use with Loader component
  101.   - Allocate buffer and load animations textfile given direct path */
  102.   _kernel_oserror *err;
  103.  
  104.   /* Allocate flex buffer for data */
  105.   if(!flex_alloc(buffer, sizeof(SF_MapTilesSetHdr))) {
  106.     WRITE_GERR(shared_err_block, "NoMem");
  107.     return &shared_err_block;
  108.   }
  109.  
  110.   /* Read animations directly into our buffer */
  111.   err = load_animsfilepath(file_path, (SF_MapTilesSetHdr **)buffer, true);
  112.   if(err != NULL)
  113.     flex_free(buffer);
  114.  
  115.   return err;
  116. }
  117.  
  118. /*
  119.  * File saving routines
  120.  */
  121.  
  122. _kernel_oserror *save_animsfile(char *filepath, SF_MapTilesSetHdr *putanimations)
  123. {
  124.   /* Write textfile with animations */
  125.   _kernel_last_oserror(); /* reset SCL's error recording */
  126.  
  127.   FILE *animdata = fopen(filepath, "w");
  128.   if(animdata == NULL) {
  129.     THROW(_kernel_last_oserror()) /* any OS error? */
  130.     WRITE_ERR_SUB1(shared_err_block, "OpenOutFail", filepath);
  131.     return &shared_err_block; /* failure */
  132.   }
  133.   int num_outputs = fprintf(animdata, "splash1:%d,%d,%d,%d\n",
  134.     putanimations->splash_anim_1[0],
  135.     putanimations->splash_anim_1[1],
  136.     putanimations->splash_anim_1[2],
  137.     putanimations->splash_anim_1[3]);
  138.   if(num_outputs < 0)
  139.     goto WriteFail;
  140.  
  141.   num_outputs = fprintf(animdata, "splash2:%d,%d,%d,%d\n",
  142.     putanimations->splash_anim_2[0],
  143.     putanimations->splash_anim_2[1],
  144.     putanimations->splash_anim_2[2],
  145.     putanimations->splash_anim_2[3]);
  146.   if(num_outputs < 0)
  147.     goto WriteFail;
  148.  
  149.   num_outputs = fprintf(animdata,"s2triggers:%d,%d,%d,%d\n",
  150.     putanimations->splash_2_triggers[0],
  151.     putanimations->splash_2_triggers[1],
  152.     putanimations->splash_2_triggers[2],
  153.     putanimations->splash_2_triggers[3]);
  154.   if(num_outputs < 0)
  155.     goto WriteFail;
  156.  
  157.   fclose(animdata);
  158.   return NULL; /* success */
  159.  
  160. WriteFail:
  161.   fclose(animdata);
  162.   THROW(_kernel_last_oserror()) /* any OS error? */
  163.   WRITE_ERR_SUB1(shared_err_block, "WriteFail", filepath);
  164.   return &shared_err_block; /* failure */
  165. }
  166.  
  167. /*
  168.  * General utility functions
  169.  */
  170.  
  171. char *copystring(char *string)
  172. {
  173.   /* copy string into newly allocated memory */
  174.   char *ptr;
  175.  
  176.   ptr = malloc(strlen(string)+1);
  177.   if(ptr == NULL)
  178.     err_complain(255,msgs_global("NoMem"));
  179.   else
  180.     strcpy(ptr, string);
  181.   return ptr;
  182. }
  183.  
  184. /* ----------------------------------------------------------------------- */
  185.  
  186. _kernel_oserror *showgadget(ObjectId window, ComponentId gadget)
  187. {
  188.   int height;
  189.   BBox pos;
  190.   THROW(gadget_get_bbox(0, window, gadget, &pos))
  191.   if(pos.ymin < 0) /* already shown */
  192.     return NULL;
  193.   /* shift the icon into the window to show the button */
  194.   height = pos.ymax - pos.ymin;
  195.   pos.ymin = -pos.ymin; /* implicitly preserves dist. icbottom-to-wintop */
  196.   pos.ymax = pos.ymin+height; /* keep dist. icbottom-to-ictop */
  197.   return gadget_move_gadget(0, window, gadget, &pos);
  198. }
  199.  
  200. /* ----------------------------------------------------------------------- */
  201.  
  202. _kernel_oserror *hidegadget(ObjectId window, ComponentId gadget)
  203. {
  204.   int height;
  205.   BBox pos;
  206.   THROW(gadget_get_bbox(0, window, gadget, &pos))
  207.   if(pos.ymin > 0) /* already hidden */
  208.     return NULL;
  209.   /* shift the icon off the top to show the button */
  210.   height = pos.ymax - pos.ymin;
  211.   pos.ymin = -pos.ymin; /* implicitly preserves dist. icbottom-to-wintop */
  212.   pos.ymax = pos.ymin+height; /* keep dist. icbottom-to-ictop */
  213.   return gadget_move_gadget(0, window, gadget, &pos);
  214. }
  215.  
  216. /* ----------------------------------------------------------------------- */
  217.  
  218. _kernel_oserror *set_gadget_faded(bool fade, ObjectId id, ComponentId gad)
  219. {
  220.   unsigned int flags_settings;
  221.  
  222.   THROW(gadget_get_flags(0, id, gad, &flags_settings))
  223.   if(fade) {
  224.     if(FLAG_SET(flags_settings, Gadget_Faded))
  225.       return NULL;
  226.     flags_settings |= Gadget_Faded;
  227.   }
  228.   else {
  229.     if(!FLAG_SET(flags_settings, Gadget_Faded))
  230.       return NULL;
  231.     flags_settings &= (~Gadget_Faded);
  232.   }
  233.   return gadget_set_flags(0, id, gad, flags_settings);
  234. }
  235.  
  236. /* ----------------------------------------------------------------------- */
  237.  
  238. _kernel_oserror *getscreencentre(int *centreX,int *centreY)
  239. {
  240.   /* Get screen centre */
  241.   int XWindLimit,YWindLimit;
  242.   int XEigFactor,YEigFactor;
  243.   _kernel_swi_regs regs;
  244.  
  245.   regs.r[0]=-1; /* current mode */
  246.   regs.r[1]=11; /* no of x pixels on screen-1 */
  247.   THROW(_kernel_swi(OS_ReadModeVariable,®s,®s))
  248.   XWindLimit=regs.r[2];
  249.  
  250.   regs.r[0]=-1; /* current mode */
  251.   regs.r[1]=12; /* no of y pixels on screen-1 */
  252.   THROW(_kernel_swi(OS_ReadModeVariable,®s,®s))
  253.   YWindLimit=regs.r[2];
  254.  
  255.   regs.r[0]=-1; /* current mode */
  256.   regs.r[1]=4; /* X eigen factor */
  257.   THROW(_kernel_swi(OS_ReadModeVariable,®s,®s))
  258.   XEigFactor=regs.r[2];
  259.  
  260.   regs.r[0]=-1; /* current mode */
  261.   regs.r[1]=5; /* Y eigen factor */
  262.   THROW(_kernel_swi(OS_ReadModeVariable,®s,®s))
  263.   YEigFactor=regs.r[2];
  264.  
  265.   *centreX = (XWindLimit<<XEigFactor)/2;
  266.   *centreY = (YWindLimit<<YEigFactor)/2;
  267.   return NULL;
  268. }
  269.  
  270. /* ----------------------------------------------------------------------- */
  271.  
  272. char *tail(char *pathname, int length)
  273. {
  274.   char *ptr;
  275.   int dotcount;
  276.  
  277.   ptr = (char *)((int)pathname + strlen(pathname)); /* terminator */
  278.   dotcount = 0;
  279.   while(ptr > pathname && dotcount<length) {
  280.     ptr--; /* scan string backwards from terminator */
  281.     if(*ptr == '.')
  282.       dotcount++;
  283.   }
  284.   if(dotcount >= length)
  285.     return (char *)((int)ptr + 1);
  286.   return ptr;
  287. }
  288.  
  289. /*
  290.  * Check header of tiles set for valid animations data
  291.  */
  292.  
  293. bool check_animations(SF_MapTilesSetHdr **hdr)
  294. {
  295.   /* Check that the tile numbers are valid */
  296.   if(!_check_anims_limits((*hdr)->splash_anim_1, (*hdr)->lasttile_num)
  297.   || !_check_anims_limits((*hdr)->splash_anim_2, (*hdr)->lasttile_num)) {
  298.     if(!dialogue_confirm(msgs_lookup("DuffAnimsBnd")))
  299.       return false;
  300.   }
  301.  
  302.   /* Friendly check that the splash triggers cover the splash animation */
  303.   bool covered, one_not_covered = false;
  304.   bool anims_eq = true;
  305.   for(int a = 0; a < 4; a++) {
  306.     covered = false;
  307.     /* Check that one of the triggers covers this splash tile... */
  308.     for(int b = 0; b < 4 && !covered; b++) {
  309.       if((*hdr)->splash_2_triggers[b] == (*hdr)->splash_anim_2[a]
  310.       || ((*hdr)->splash_2_triggers[b]+1) == (*hdr)->splash_anim_2[a])
  311.         covered = true;
  312.     }
  313.     if(!covered)
  314.       one_not_covered = true;
  315.     if((*hdr)->splash_anim_1[a] != (*hdr)->splash_anim_2[a])
  316.       anims_eq = false;
  317.   }
  318.  
  319.   if(one_not_covered && !anims_eq) {
  320.     if(!dialogue_confirm(msgs_lookup("Splash2Warn")))
  321.       return false;
  322.   }
  323.   return true;
  324. }
  325.  
  326. /*
  327.  * Check sprite areas for potential tile/planet graphics
  328.  */
  329.  
  330. bool contains_valid_planets(spriteareaheader **sa)
  331. {
  332.   int numsprites = (*sa)->sprite_count;
  333.  
  334.   nobudge_register(1024);
  335.   spriteheader *sph = (spriteheader *)((int)(*sa) + (*sa)->first);
  336.  
  337.   hourglass_on();
  338.   for(int sprite = 0; sprite < numsprites; sprite++) {
  339.  
  340.     /* Check sprite header */
  341.     char spritename[13];
  342.     strncpy(spritename, sph->name, sizeof(spritename)-1);
  343.     if(spritehdr_validpla(sph, spritename) >= 0) {
  344.       hourglass_off();
  345.       nobudge_deregister();
  346.       return true; /* found */
  347.     }
  348.     sph = (spriteheader *)((int)sph+sph->size);
  349.   }
  350.   hourglass_off();
  351.  
  352.   nobudge_deregister();
  353.   return false; /* no valid planets in sprite area */
  354. }
  355.  
  356. /* ----------------------------------------------------------------------- */
  357.  
  358. bool contains_valid_tiles(spriteareaheader **sa)
  359. {
  360.   int numsprites = (*sa)->sprite_count;
  361.  
  362.   nobudge_register(1024);
  363.   spriteheader *sph = (spriteheader *)((int)(*sa) + (*sa)->first);
  364.  
  365.   hourglass_on();
  366.   for(int sprite = 0; sprite < numsprites; sprite++) {
  367.  
  368.     /* Check sprite header */
  369.     char spritename[13];
  370.     strncpy(spritename, sph->name, sizeof(spritename)-1);
  371.     if(spritehdr_validtile(sph, spritename) >= 0) {
  372.       hourglass_off();
  373.       nobudge_deregister();
  374.       return true; /* found */
  375.     }
  376.     
  377.     sph = (spriteheader *)((int)sph + sph->size);
  378.   }
  379.   hourglass_off();
  380.  
  381.   nobudge_deregister();
  382.   return false; /* no valid tiles in sprite area */
  383. }
  384.  
  385. /* ----------------------------------------------------------------------- */
  386.  
  387. bool dialogue_confirm(const char *mess)
  388. {
  389.   strncpy(shared_err_block.errmess, mess, sizeof(shared_err_block.errmess)-1);
  390.  
  391.   if(wimp_version >= 321) {
  392.     /* Nice error box */
  393.     return (wimp_report_error(&shared_err_block, (1u << 8)|(1u << 11), taskname, NULL, NULL, msgs_lookup("ConButtons")) == 3);
  394.   }
  395.   else {
  396.     /* Backwards compatibility */
  397.     return (wimp_report_error(&shared_err_block, Wimp_ReportError_OK|Wimp_ReportError_Cancel, taskname) == Wimp_ReportError_OK);
  398.   }
  399. }
  400.  
  401. /* ----------------------------------------------------------------------- */
  402.  
  403. int delete_object_handler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
  404. {
  405.   /* Generic handler for deleting an object */
  406.   RE(toolbox_delete_object(0, id_block->self_id))
  407.  
  408.   return 1; /* claim event */
  409. }
  410.  
  411. /* ----------------------------------------------------------------------- */
  412. /*                         Private functions                               */
  413.  
  414. static bool _check_anims_limits(char *anims_array, int last_tilenum)
  415. {
  416.   for(int i = 0; i < 4; i++) {
  417.     if((anims_array[i] > last_tilenum && anims_array[i] != 255) 
  418.     || anims_array[i] < 0)
  419.       return false;
  420.   }
  421.   return true;
  422. }
  423.  
  424. /* ----------------------------------------------------------------------- */
  425.  
  426. _kernel_oserror *load_animsfilepath(char *filepath, SF_MapTilesSetHdr **getanimations, bool err_if_absent)
  427. {
  428.   /* Load animations textfile given explicit filepath */
  429.   int a, b ,c, d, numread;
  430.  
  431.   nobudge_register(256);  /* remove a layer of indirection */
  432.   SF_MapTilesSetHdr *anims_ptr = *getanimations;
  433.  
  434.   FILE *animdata = fopen(filepath, "r");
  435.   if(animdata != NULL) {
  436.     /* Read values from textfile (these may be overwritten subsequently by text from dialogue box) */
  437.     numread = fscanf(animdata, "splash1:%d,%d,%d,%d\n", &a, &b, &c, &d);
  438.     if(numread == EOF || numread<4 || a>255 || b>255 || c>255 || d>255) {
  439.       fclose(animdata);
  440.       WRITE_ERR(shared_err_block, "BadAnimsFile");
  441.       return &shared_err_block; /* failure */
  442.     }
  443.     anims_ptr->splash_anim_1[0] = a;
  444.     anims_ptr->splash_anim_1[1] = b;
  445.     anims_ptr->splash_anim_1[2] = c;
  446.     anims_ptr->splash_anim_1[3] = d;
  447.  
  448.     numread = fscanf(animdata, "splash2:%d,%d,%d,%d\n", &a, &b, &c, &d);
  449.     if(numread == EOF || numread<4 || a>255 || b>255 || c>255 || d>255) {
  450.       fclose(animdata);
  451.       WRITE_ERR(shared_err_block, "BadAnimsFile");
  452.       return &shared_err_block; /* failure */
  453.     }
  454.     anims_ptr->splash_anim_2[0] = a;
  455.     anims_ptr->splash_anim_2[1] = b;
  456.     anims_ptr->splash_anim_2[2] = c;
  457.     anims_ptr->splash_anim_2[3] = d;
  458.  
  459.     numread = fscanf(animdata, "s2triggers:%d,%d,%d,%d\n", &a, &b, &c, &d);
  460.     if(numread == EOF || numread<4 || a>255 || b>255 || c>255 || d>255) {
  461.       fclose(animdata);
  462.       WRITE_ERR(shared_err_block, "BadAnimsFile");
  463.       return &shared_err_block; /* failure */
  464.     }
  465.     anims_ptr->splash_2_triggers[0] = a;
  466.     anims_ptr->splash_2_triggers[1] = b;
  467.     anims_ptr->splash_2_triggers[2] = c;
  468.     anims_ptr->splash_2_triggers[3] = d;
  469.  
  470.     fclose(animdata);
  471.   }
  472.   else {
  473.     /* Blank data, then */
  474.     memset(&(anims_ptr->splash_anim_1), 0, sizeof(&(anims_ptr)->splash_anim_1));
  475.     memset(&(anims_ptr->splash_anim_2), 0, sizeof(&(anims_ptr)->splash_anim_2));
  476.     memset(&(anims_ptr->splash_2_triggers), 0, sizeof(&(anims_ptr)->splash_2_triggers));
  477.     if(err_if_absent) {
  478.       WRITE_ERR(shared_err_block, "NoAnimFile");
  479.       return &shared_err_block; /* failure */
  480.     }
  481.   }
  482.   nobudge_deregister();
  483.   return NULL; /* success */
  484. }
  485.